/**
 * www.easyplatform.cn ©2016
 */
package cn.easyplatform.studio.web.editors.project;

import cn.easyplatform.entities.beans.project.DeviceMapBean;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.studio.StudioApp;
import cn.easyplatform.studio.cmd.identity.UpdateProjectCmd;
import cn.easyplatform.studio.context.Contexts;
import cn.easyplatform.studio.utils.*;
import cn.easyplatform.studio.vos.TemplateVo;
import cn.easyplatform.studio.web.editors.AbstractPanelEditor;
import cn.easyplatform.studio.web.editors.Savable;
import cn.easyplatform.studio.web.editors.support.CodeFormatter;
import cn.easyplatform.studio.web.editors.support.ZulXsdUtil;
import cn.easyplatform.studio.web.layout.WorkbenchController;
import cn.easyplatform.type.DeviceType;
import cn.easyplatform.web.ext.cmez.CMeditor;
import org.apache.commons.io.IOUtils;
import org.zkoss.image.AImage;
import org.zkoss.util.resource.Labels;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.event.EventListener;
import org.zkoss.zk.ui.event.Events;
import org.zkoss.zk.ui.event.UploadEvent;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.*;

import java.io.*;
import java.util.List;

/**
 * @author <a href="mailto:shiny_vc@163.com">陈云亮</a> <br/>
 * @since 2.0.0 <br/>
 */
public class AppPageEditor extends AbstractPanelEditor implements Savable {
    private int type;

    private Iframe canvas;

    private CMeditor editor;

    private Label errorMsg;

    private boolean dirty;

    private String title;

    private Window templateWindow;

    private Grid chooseTmpGrid;

    private String pathName;

    private List<TemplateVo> templateVos;

    private TemplateVo currentTemplateVo;

    TemplateUtil.TemplateType templateType;

    public AppPageEditor(WorkbenchController workbench, String id, int type) {
        super(workbench, id);
        this.type = type;
    }

    @Override
    public void create(Object... args) {
        String image = type > 2 ? "phone.gif" : "computer.gif";
        String name = "menu.project.pc.login";
        String xml = null;
        String uri = type > 2 ? "~./include/editor/project/page_mobile.zul" : "~./include/editor/project/page.zul";
        templateType = TemplateUtil.TemplateType.TEMPLATE_TYPE_DESKTOP_LOGIN;
        switch (type) {
            case 1:
                templateType = TemplateUtil.TemplateType.TEMPLATE_TYPE_DESKTOP_LOGIN;
                name = "menu.project.pc.login";
                break;
            case 2:
                templateType = TemplateUtil.TemplateType.TEMPLATE_TYPE_DESKTOP_MAIN;
                name= "menu.project.pc.main";
                break;
            case 3:
                templateType = TemplateUtil.TemplateType.TEMPLATE_TYPE_MOBILE_LOGIN;
                name= "menu.project.mobile.login";
                break;
            case 4:
                templateType = TemplateUtil.TemplateType.TEMPLATE_TYPE_MOBILE_MAIN;
                name= "menu.project.mobile.main";
                break;
        }
        templateVos = new TemplateUtil().getTemplateWithType(templateType);
        currentTemplateVo = new TemplateUtil().getTemplateVoBackups(templateType);
        for (DeviceMapBean dm : Contexts.getProject().getDevices()) {
            if (dm.getType().equals(DeviceType.AJAX.getName())) {
                if (type == 1)
                    xml = dm.getLoginPage();
                else if (type == 2)
                    xml = dm.getMainPage();
            } else if (dm.getType().equals(DeviceType.MOBILE.getName())) {
                if (type == 3) {
                    xml = dm.getLoginPage();
                } else if (type == 4) {
                    xml = dm.getMainPage();
                }
            }
        }
        if (xml != null) {
            StringBuilder sb = new StringBuilder();
            sb.append("<?taglib uri=\"http://www.zkoss.org/dsp/web/core\" prefix=\"c\"?>\n");
            sb.append(xml);
            xml = sb.toString();
        }
        title = Labels.getLabel(name);
        Idspace is = createPanel(title, "~./images/" + image, uri);
        canvas = (Iframe) is.getFellow("page_iframe_canvas");

        editor = (CMeditor) is.getFellow("page_cmeditor_editor");
        editor.setTheme(Contexts.getUser().getEditorTheme());
        editor.setValue(xml);
        editor.addEventListener(Events.ON_CHANGING, this);

        Toolbarbutton chooseTemp = (Toolbarbutton) is.getFellow("page_toolbarbutton_chooseTemp");
        chooseTemp.addEventListener(Events.ON_CLICK, this);

        Toolbarbutton imageImport = (Toolbarbutton) is.getFellow("page_toolbarbutton_imageImport");
        imageImport.addEventListener(Events.ON_CLICK, this);

        Toolbarbutton fileImport = (Toolbarbutton) is.getFellow("page_toolbarbutton_fileImport");
        fileImport.addEventListener(Events.ON_UPLOAD, this);

        Toolbarbutton storeImport = (Toolbarbutton) is.getFellow("page_toolbarbutton_storeImport");
        storeImport.addEventListener(Events.ON_CLICK, this);

        Toolbarbutton pageExport = (Toolbarbutton) is.getFellow("page_toolbarbutton_pageExport");
        pageExport.addEventListener(Events.ON_CLICK, this);

        Toolbarbutton storeExport = (Toolbarbutton) is.getFellow("page_toolbarbutton_storeExport");
        storeExport.addEventListener(Events.ON_CLICK, this);

        String windowID = null;
        String gridID = null;
        boolean isDeskTop = false;
        Div windowDiv = null;
        if (type > 2) {
            if (type == 3) {
                windowID = "pageMobile_window_mobileLogin";
                gridID = "pageMobile_grid_mobileLogin";
            } else if (type == 4) {
                windowID = "pageMobile_window_mobileMain";
                gridID = "pageMobile_grid_mobileMain";
            }
            windowDiv = (Div) is.getFellow("pageMobile_div_template");
        } else {
            if (type == 1) {
                windowID = "projectPage_window_desktopLogin";
                gridID = "projectPage_grid_desktopLogin";
            } else if (type == 2) {
                windowID = "projectPage_window_desktopMain";
                gridID = "projectPage_grid_desktopMain";
            }
            isDeskTop = true;
            windowDiv = (Div) is.getFellow("projectPage_div_template");
        }
        setWindow(windowID, gridID, isDeskTop, windowDiv);

        redrawGrid();

        errorMsg = (Label) is.getFellow("page_label_errorMsg");

        tab.setAutoClose(false);
        tab.addEventListener(Events.ON_CLOSE, this);
        if (type > 2) {
            Div loginDiv = (Div) is.getFellow("page_div_canvas");
            Image bgImage = (Image) is.getFellow("page_image_bg");
            Clients.evalJavaScript("setBGImage('" + bgImage.getUuid() + "','" + loginDiv.getUuid() + "')");
        }
        redraw();
        String hisPath = StudioApp.getServletContext().getRealPath(new TemplateUtil().getHisFilePathBackups(templateType));
        File file = new File(hisPath);
        if (file.isDirectory() && file.list().length > 0) {
            String path = StudioApp.getServletContext().getRealPath(new TemplateUtil().getCoreFilePath(templateType));
            try {
                FileUtil.copyDir(hisPath, path);
            } catch (IOException e) {
                e.printStackTrace();
            }
            FileUtil.delAllFile(hisPath);
        }
    }

    private void setWindow(String windowID, String gridID, boolean isDeskTop, Div windowDiv){
        templateWindow = new Window();
        templateWindow.setId(windowID);
        templateWindow.setTitle(Labels.getLabel("wiard.template"));
        templateWindow.setBorder("normal");
        templateWindow.setPosition("right,bottom");
        templateWindow.setWidth("79.5%");
        templateWindow.setHeight("95%");
        templateWindow.setMaximizable(true);
        templateWindow.setSizable(true);
        templateWindow.setClosable(true);
        templateWindow.setVisible(false);
        templateWindow.addEventListener(Events.ON_CLOSE, this);
        windowDiv.appendChild(templateWindow);

        chooseTmpGrid = new Grid();
        chooseTmpGrid.setId(gridID);
        chooseTmpGrid.setVflex("1");
        chooseTmpGrid.setStyle("overflow:auto");
        Columns columns = new Columns();
        columns.appendChild(new Column());
        columns.appendChild(new Column());
        if (isDeskTop == false) {
            columns.appendChild(new Column());
            columns.appendChild(new Column());
        }
        chooseTmpGrid.appendChild(columns);
        chooseTmpGrid.appendChild(new Rows());
        templateWindow.appendChild(chooseTmpGrid);
    }

    private void redrawGrid() {
        chooseTmpGrid.getRows().getChildren().clear();
        Row row = null;
        int size = templateVos.size();
        if (type > 2) {
            //mobile
            if (templateVos.size() % 4 != 0)
                size += (4 - templateVos.size() % 4);
            for (int index = 0; index < size; index++) {
                if (index % 4 == 0) {
                    if (row != null)
                        chooseTmpGrid.getRows().appendChild(row);
                    row = new Row();
                    row.setStyle("background:#e8e8e8");
                }
                Image image = new Image();
                if (templateVos.size() - 1 >= index) {
                    TemplateVo vo = templateVos.get(index);
                    image.setWidth("80%");
                    image.setId(vo.getProductIdentifier());
                    image.setStyle("margin:10% 10%");
                    if (vo.getProductPreview() != null && vo.getProductPreview().size() > 0) {
                        try {
                            InputStream inputStream = FileUtil.getJarImageWithFileName(StudioApp.getServletContext().getRealPath(
                                    "/WEB-INF/lib/template/" + vo.getProductIdentifier()),
                                    vo.getProductPreview().get(0));
                            image.setContent(new AImage(vo.getProductPreview().get(0), inputStream));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    image.addEventListener(Events.ON_CLICK, this);
                }
                row.appendChild(image);
            }
        } else {
            //desktop
            if (templateVos.size() % 2 == 1)
                size++;
            for (int index = 0; index < size; index++) {
                if (index % 2 == 0) {
                    if (row != null)
                        chooseTmpGrid.getRows().appendChild(row);
                    row = new Row();
                    row.setStyle("background:#e8e8e8");
                }
                Image image = new Image();
                if (templateVos.size() - 1 >= index) {
                    TemplateVo vo = templateVos.get(index);
                    image.setWidth("96%");
                    image.setId(vo.getProductIdentifier());
                    image.setStyle("margin:2%");
                    if (vo.getProductPreview() != null && vo.getProductPreview().size() > 0) {
                        try {
                            InputStream inputStream = FileUtil.getJarImageWithFileName(StudioApp.getServletContext().getRealPath(
                                    "/WEB-INF/lib/template/" + vo.getProductIdentifier()),
                                    vo.getProductPreview().get(0));
                            image.setContent(new AImage(vo.getProductPreview().get(0), inputStream));
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    image.addEventListener(Events.ON_CLICK, this);
                }
                row.appendChild(image);
            }
        }

        if (row != null)
            chooseTmpGrid.getRows().appendChild(row);
    }

    private void redraw() {
        String content = (String) editor.getValue();
        //String content = content1.replaceAll("/template/", "/WEB-INF/template/" + Contexts.getProject().getId() + "/");
        if (!Strings.isBlank(content)) {
            try {
                CodeFormatter.formatXML(ZulXsdUtil
                        .buildDocument(content));
                //Component c = Executions.createComponentsDirectly(content, "zul", null, null);
                //if (type % 2 == 0)
                //    c.setAttribute("m", "");
                //c.detach();
                canvas.getDesktop().getSession().setAttribute("content", content);
                String srcPath = "/richlet/dyamic?s=" + System.currentTimeMillis();
                canvas.setSrc(srcPath);
                errorMsg.setValue("");
            } catch (Exception ex) {
                String msg = ex.getMessage();
                if (msg != null) {
                    int idx = msg.indexOf("for class");
                    if (idx > 0)
                        msg = msg.substring(0, idx);
                    else if ((idx = msg.indexOf("SAXParseException;")) >= 0) {
                        msg = msg.substring(idx + 18);
                    }
                } else
                    msg = "Wrong page content";
                errorMsg.setValue(msg);
            }
        }
    }

    @Override
    public void dispatch(Event event) {
        if (event.getTarget() == editor) {
            redraw();
            setDirty();
        } else if (event.getTarget() instanceof Image) {
            new TemplateUtil().copyTemplateBackups(event.getTarget().getId(), templateType);
            templateWindow.setVisible(false);
            String path = null;
            String page = event.getTarget().getId();
            for (TemplateVo vo :
                    templateVos) {
                if (vo.getProductIdentifier().equals(page)) {
                    path = new TemplateUtil().getCoreFilePath(templateType) + "/" + vo.getZULFiles().get(0);
                }
            }
            setContent(path);
        } else if (event.getTarget().getId().equals("page_toolbarbutton_chooseTemp")) {
            templateWindow.setVisible(true);
            templateWindow.doPopup();
        } else if (event.getTarget().equals(templateWindow)) {
            templateWindow.setVisible(false);
            event.stopPropagation();
        } else if (event.getTarget().getId().equals("page_toolbarbutton_imageImport")) {
            List<String> pathList = FileUtil.getFilePathWithDirectory(StudioApp.getServletContext().getRealPath(
                    new TemplateUtil().getCoreFilePath(templateType) + "/img"));
            if (pathList != null && pathList.size() > 0) {
        /*AbstractView.createAppPageImageView(new EditorCallback<String>() {
            @Override
            public String getValue() {
                return null;
            }

            @Override
            public void setValue(String value) {
                redraw();
                setDirty();
            }

            @Override
            public String getTitle() {
                return Labels.getLabel("editor.template.image.import");
            }

            @Override
            public Page getPage() {
                return canvas.getPage();
            }

            @Override
            public Editor getEditor() {
                return null;
            }
        }, templateType, event.getTarget()).doOverlapped();*/
            } else
                WebUtils.showInfo(Labels.getLabel("editor.noImage.error"));
        } else if (event.getTarget().getId().equals("page_toolbarbutton_fileImport")) {
            UploadEvent ue = (UploadEvent) event;
            byte[] data = ue.getMedia().getByteData();
            FileUtil.mkdirForNoExists(StudioApp.getServletContext().getRealPath("/WEB-INF/template/tmp/" +
                    Contexts.getProject().getId() + "/"));
            String zipPath = StudioApp.getServletContext().getRealPath("/WEB-INF/template/tmp/" + Contexts.getProject().getId()
                    + "/" + ue.getMedia().getName());
            //写文件
            FileUtil.setBytesWithFile(data, zipPath);
            //zip解压
            ZipUtil.unZip(new File(zipPath), StudioApp.getServletContext().getRealPath("/WEB-INF/template/tmp/" +
                    Contexts.getProject().getId() + "/"));
            String tempFile = "/WEB-INF/template/tmp/" + Contexts.getProject().getId() + "/" +
                    ue.getMedia().getName().substring(0,ue.getMedia().getName().length() - 4) + "/";
            boolean isLegal = new TemplateUtil().templateIsLegal(tempFile, templateType);
            if (isLegal == true) {
                //添加到对应目录中
                try {
                    FileUtil.copyDir(StudioApp.getServletContext().getRealPath(tempFile),
                            StudioApp.getServletContext().getRealPath(new TemplateUtil().getCoreFilePath(templateType)));
                } catch (IOException e) {
                    e.printStackTrace();
                }
                WebUtils.showSuccess(Labels.getLabel("editor.template.file.import.success"));
                currentTemplateVo = new TemplateUtil().getTemplateVoBackups(templateType);
                setContent(new TemplateUtil().getCoreFilePath(templateType) + "/" + currentTemplateVo.getZULFiles().get(0));
            } else
                WebUtils.showInfo(Labels.getLabel("editor.template.file.import.fileError"));
            //删除临时目录
            FileUtil.delFolder(StudioApp.getServletContext().getRealPath("/WEB-INF/template/tmp/"));
        } else if (event.getTarget().getId().equals("page_toolbarbutton_pageExport")) {
            Boolean success = createNewTemplate();
            if (success == true)
                WebUtils.showSuccess(Labels.getLabel("editor.template.file.export.success"));
        } else if (event.getTarget().getId().equals("page_toolbarbutton_storeImport")) {

        } else if (event.getTarget().getId().equals("page_toolbarbutton_storeExport")) {

        }
    }

    private boolean createNewTemplate() {
        //临时目录
        String newPath = StudioApp.getServletContext().getRealPath("/WEB-INF/template/tmp/" + Contexts.getProject().getId() + "/");
        FileUtil.mkdirForNoExists(newPath);
        //拷贝到临时目录
        String uuidString = StringUtil.getShortUUID();
        try {
            FileUtil.copyDir(StudioApp.getServletContext().getRealPath(new TemplateUtil().getCoreFilePath(templateType)),
                    StudioApp.getServletContext().getRealPath("/WEB-INF/template/tmp/" + Contexts.getProject().getId() + "/" + uuidString));
        } catch (IOException e) {
            e.printStackTrace();
        }
        String productPath = "/WEB-INF/template/tmp/" + Contexts.getProject().getId() + "/" + uuidString;
        //打包
        String zipPath = StudioApp.getServletContext().getRealPath(productPath + ".zip");
        try {
            ZipUtil.compress(StudioApp.getServletContext().getRealPath(productPath), zipPath);
        } catch (Exception e) {
            e.printStackTrace();
        }
        //下载
        try {
            Filedownload.save(new File(zipPath),null);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        return true;
    }
    @Override
    public void onEvent(Event event) throws Exception {
        if (event.getTarget() == tab) {
            if (Contexts.getUser().isAuthorized("save")&&dirty) {
                Messagebox.show(Labels.getLabel("message.confirm.close"),
                        Labels.getLabel("message.title.confirm"),
                        Messagebox.YES | Messagebox.NO | Messagebox.CANCEL,
                        Messagebox.QUESTION, new EventListener<Event>() {
                            @Override
                            public void onEvent(Event event) throws Exception {
                                if (event.getName().equals(Messagebox.ON_YES)
                                        || event.getName().equals(
                                        Messagebox.ON_NO)) {
                                    if (event.getName().equals(
                                            Messagebox.ON_YES)) {
                                        if (save())
                                            close();
                                    } else
                                        close();
                                }
                            }
                        });
            } else {
                close();
            }
        } else
            dispatch(event);
    }

    @Override
    public void close() {
        tab.setAutoClose(true);
        super.close();
    }

    private void setDirty() {
        dirty = true;
        workbench.setDisabled("save", false);
        workbench.setDisabled("saveAll", false);
        tab.setLabel("*" + title);
    }

    @Override
    public boolean isDirty() {
        return dirty;
    }

    @Override
    public boolean save() {
        String content1 = (String) editor.getValue();
        String content = (String) editor.getValue();
        if (!content.trim().equals("")) {
            /*Document document = ZulXsdUtil.buildDocument(content);
            content = document.getRootElement().toXML();*/
            content = content.replace("<?taglib uri=\"http://www.zkoss.org/dsp/web/core\" prefix=\"c\"?>\n", "");
            DeviceMapBean dm = null;
            if (type < 3) {
                dm = getDeviceMapping(DeviceType.AJAX);
                if (dm == null) {
                    dm = new DeviceMapBean();
                    dm.setType(DeviceType.AJAX.getName());
                    Contexts.getProject().getDevices().add(dm);
                }
            } else {
                dm = getDeviceMapping(DeviceType.MOBILE);
                if (dm == null) {
                    dm = new DeviceMapBean();
                    dm.setType(DeviceType.MOBILE.getName());
                    Contexts.getProject().getDevices().add(dm);
                }
            }
            if (type % 2 == 0)
                dm.setMainPage(content);
            else
                dm.setLoginPage(content);
            StudioApp.execute(new UpdateProjectCmd());
            dirty = false;
            tab.setLabel(title);
            workbench.setDisabled("save", true);
        }
        //写到前端
        if (new AppServiceFileUtils().webContainerIsLegal()) {
            String servicePath = StudioApp.getServletContext().getRealPath(
                    new TemplateUtil().getCoreFilePath(templateType));
            String appPath = new AppServiceFileUtils().getFilePath("",templateType);
            FileUtil.mkdirForNoExists(appPath);
            try {
                FileUtil.copyDir(servicePath, appPath);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String hisPath = StudioApp.getServletContext().getRealPath(new TemplateUtil().getHisFilePathBackups(templateType));
            FileUtil.delAllFile(hisPath);
        } else {
            WebUtils.showInfo(Labels.getLabel("editor.appPath.error"));
        }
        return true;
    }

    private void setContent(String path) {
        String xml = null;
        xml = getZulcode(path);
        StringBuilder sb = new StringBuilder();
        sb.append("<?taglib uri=\"http://www.zkoss.org/dsp/web/core\" prefix=\"c\"?>\n");
        //sb.append("<div xmlns:n=\"native\" xmlns:c=\"client\" hflex=\"1\" vflex=\"1\">");
        //xml = xml.replace("\uFEFF","");
        sb.append(xml);//.append("</div>");
        xml = sb.toString();
        String replacePath = null;
        if (templateType == TemplateUtil.TemplateType.TEMPLATE_TYPE_DESKTOP_LOGIN)
            replacePath = "d0";
        if (templateType == TemplateUtil.TemplateType.TEMPLATE_TYPE_DESKTOP_MAIN)
            replacePath = "d1";
        if (templateType == TemplateUtil.TemplateType.TEMPLATE_TYPE_MOBILE_LOGIN)
            replacePath = "m0";
        if (templateType == TemplateUtil.TemplateType.TEMPLATE_TYPE_MOBILE_MAIN)
            replacePath = "m1";
        xml = xml.replaceAll("#\\{708\\}", replacePath);
        editor.setValue(xml);
        redraw();
        setDirty();
    }

    private DeviceMapBean getDeviceMapping(DeviceType type) {
        for (DeviceMapBean dm : Contexts.getProject().getDevices()) {
            if (dm.getType().equals(type.getName()))
                return dm;
        }
        return null;
    }

    private String getZulcode(String path) {
        if (path != null) {
            String xml = "";
            try {
                InputStream inputStream = new FileInputStream(new File(StudioApp.getServletContext().getRealPath(path)));
                xml = IOUtils.toString(inputStream, "UTF-8");
                xml = xml.replaceAll("\uFEFF", "");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return xml;
        }
        return "";
    }

    @Override
    public void setTheme(String theme) {
        editor.setTheme(theme);
    }
}
